import random
import re
from datetime import datetime

from flask import current_app, jsonify
from flask import make_response
from flask import request
from flask import session

from info import constants, db
from info import redis_store
from info.lib.yuntongxun.sms import CCP
from info.models import User
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET
from . import passport_blu



@passport_blu.route('/logout')
def logout():
    """退出鞥路"""
    session.pop('user_id',None)
    session.pop('nick_name',None)
    session.pop('mobiile',None)

    return jsonify(erron=RET.OK, errmsg='退出成功')


@passport_blu.route('/login', methods=["POST"])
def login():
    """
    1. 接受参数并判空处理
    2. 数据库查询指定用户数据
    3. 取出密码与前段传递过来的密码比对
    4. 成功之后保持登陆状态
    5. 返回成功响应
    """
    # 1. 接受参数并判空处理
    json_data = request.json
    print(json_data)
    mobile = json_data.get("mobile")
    passport = json_data.get("passport")
    # 1.1判空
    if not all([mobile, passport]):
        return jsonify(erron=RET.PARAMERR, errmsg='参数不全')
    # 1.2判断手机号是否符合格式
    if not re.match(r"^1[3578][0-9]{9}$", mobile):
        return jsonify(erron=RET.DATAERR, errmsg='手机号匹配错误')
    # 2数据库查询用户数据
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erron=RET.DBERR, errmsg='数据库查询错误')
    # 2.1 判断用户书否存在
    if not user:
        return jsonify(erron=RET.USERERR, errmsg='该用户不存在')
    # 3. 校验密码
    if not user.check_password(passport):
        return jsonify(erron=RET.DATAERR, errmsg='密码输入错误')
    # 4. 保存用户状态
    session['user_id'] = user.id
    session['nickname'] = mobile
    session['mobile'] = mobile
    # 4.1 记录最后一次登陆时间
    user.last_login = datetime.now()
    # 4.2 提交数据
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erron=RET.DBERR, errmsg='提交数据库失败')
    # 5.返回成功响应
    return jsonify(erron=RET.OK, errmsg='登陆成功')


@passport_blu.route('/image_code')
def passport():
    """获取图片验证码"""
    # 1. 获取验证码图片ID
    code_id = request.args.get('code_id')
    # 2. 生成验证码
    name, text, image = captcha.generate_captcha()
    # 3. 以取到浏览器的code_id为建 生成的验证码图片text为值存度redis缓存数据库中
    try:
        redis_store.setex('imageCodeID_' + code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        print(e)
        # 使用日志记录错误信息
        current_app.logger.error(e)
        return make_response(jsonify(errno=RET.DATAERR, errmsg="返回图片验证码失败"))
    # 返回响应内容
    resp = make_response(image)
    # 设置返回类型
    resp.headers['Content-type'] = 'image/jpg'
    return resp


@passport_blu.route('/smscode', methods=['POST'])
def send_sms():
    # 1.接受参数并判断是否有值传递过来
    # 2.判断手机号是否符合格式
    # 3.拿图片验证码的参数去redis数据库取值
    # 4.与传递过来的图片验证码做对比
    # 5.匹配成功则生成随机6位数字短信给第三方插件帮我们发送短信到客户手机
    # 6.redis 保存短信验证码内容
    # 7.返回成功响应
    # 1.1 接受参数
    json_data = request.json
    print(json_data)
    mobile = json_data.get("mobile")
    image_code = json_data.get("image_code")
    image_code_id = json_data.get("image_code_id")
    # 1.2 并判断是否有值传递过来
    if not all([mobile, image_code, image_code_id]):
        return jsonify(erron=RET.PARAMERR, errmsg='参数不全')
    # 2.判断手机号是否符合格式
    if not re.match(r"^1[3578][0-9]{9}$", mobile):
        return jsonify(erron=RET.DATAERR, errmsg='手机号匹配错误')
    # 3.拿图片验证码的参数去redis数据库取值
    try:
        real_image_code = redis_store.get('imageCodeID_' + image_code_id)
        print(real_image_code)
        if real_image_code:
            real_image_code = real_image_code.decode("UTF-8")
            print(real_image_code)
            redis_store.delete('imageCodeID_' + image_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erron=RET.DATAERR, errmsg='获取验证码失败')
    # 3.1判断验证码是否过期 验证码constants.IMAGE_CODE_REDIS_EXPIRES只有3分钟
    if not real_image_code:
        return jsonify(erron=RET.NODATA, errmsg='验证码已过期')
    # 4 对比验证码内容
    if real_image_code.upper() != image_code.upper():
        return jsonify(erron=RET.DATAERR, errmsg='验证码输入错误')
    # 4.1 判断该手机号是否已经注册过
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        user = None  # 如果查询时出现错误，也需要给user初始化，如果不初始化，会报未定义的异常
        current_app.logger.error(e)
    if user:
        # 该手机已被注册
        return jsonify(errno=RET.DATAEXIST, errmsg="该手机已被注册")
        pass

    # 5.生成并使用第三方软件发送短信给用户
    result = random.randint(0, 999999)
    sms_code = "%06d" % result
    current_app.logger.debug('短信验证码：%s' % sms_code)
    # result = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES / 60], '1')
    # print(sms_code)
    # if result == '1':
    #     return jsonify(erron=RET.DBERR, errmsg='短信验证码发送失败')

    # 6.redis 保存短信验证码内容
    try:
        redis_store.setex('SMS_' + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erron=RET.DBERR, errmsg='短信验证码存放失败')
    # 7.返回成功响应
    return jsonify(erron=RET.OK, errmsg='短信发送成功')


@passport_blu.route("/register", methods=['POST'])
def register():
    '''
    1.获取参数   手机号  短信验证码   密码
     1.1.判断参数是否有值，并判断手机号是否符合规则
    2.从redis数据库取出手机号和短信验证码
    3.对比手机号和短信验证码是否匹配
    4.初始化user模型 并存入数据库
    5.保存用户状态
    6.返回成功响应
    :return:
    '''
    # 1.获取参数   手机号  短信验证码   密码
    json_data = request.json
    print(json_data)
    mobile = json_data.get("mobile")
    sms_code = json_data.get("sms_code")
    password = json_data.get("password")
    # 2.判断参数是否有值，并判断手机号是否符合规则
    # 1.2 并判断是否有值传递过来
    if not all([mobile, sms_code, password]):
        return jsonify(erron=RET.PARAMERR, errmsg='参数不全')
    # 2.判断手机号是否符合格式
    if not re.match(r"^1[3578][0-9]{9}$", mobile):
        return jsonify(erron=RET.DATAERR, errmsg='手机号匹配错误')
    # 3.取出数据库的短信验证码与用户输入验证码进行校验
    try:
        real_sms_code = redis_store.get('SMS_' + mobile).decode("utf-8")
        print(real_sms_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erron=RET.DBERR, errmsg='获取本地短信验证码失败')
    if not real_sms_code:
        return jsonify(erron=RET.NODATA, errmsg='短信验证码已过期')
    if real_sms_code != sms_code:
        return jsonify(erron=RET.DBERR, errmsg='短信验证码输入错误')
    # 3.1删除短信验证码
    try:
        redis_store.delete('SMS_' + mobile)
    except Exception as e:
        current_app.logger.error(e)
    # 4  初始化user
    user = User()
    user.mobile = mobile
    user.nick_name = mobile
    user.last_login = datetime.now()
    # 利用SQLALCHEMY_COMMIT_ON_TEARDOWN
    user.password = password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(erron=RET.DATAERR, errmsg='数据保存错误')
    # 5.保存用户状态
    session['user_id'] = user.id
    session['nickname'] = user.nick_name
    session['mobile'] = user.mobile
    # 6.返回成功响应

    return jsonify(erron=RET.OK, errmsg='注册成功')
